package me.wang.qrcodepay;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.MessageDigest;
import java.util.HashMap;
import java.util.Map;

import static me.wang.qrcodepay.QRcodePay.plugin;

public class PaymentRequest {

    private final String API_URL;
    private final String PID;
    private final String KEY;
    private final String name;
    private final String method;
    private String result;
    private final String order;

    public String getResponse(){
        return this.result;
    }

    public PaymentRequest(String name,String method,String order){
        this.API_URL = plugin.getConfig().getString("pay_url");
        this.PID = plugin.getConfig().getString("pid");
        this.KEY = plugin.getConfig().getString("key");
        this.name = name;
        this.method = method;
        this.order = order;
        send();
    }

    private void send() {
        try {
            Map<String, String> params = new HashMap<>();
            params.put("pid", PID);
            params.put("type", method);
            params.put("out_trade_no", order);
            params.put("notify_url", plugin.getConfig().getString("callback_url"));
            params.put("return_url", plugin.getConfig().getString("return_url"));
            params.put("name", plugin.getConfig().getString(name+".name"));
            params.put("money", plugin.getConfig().getString(name+".price"));
            if (plugin.getConfig().getInt("type") == 2){
                params.put("clientip", plugin.getConfig().getString("ip"));
            }
            params.put("sign_type", "MD5");
            String sign = generateSign(params);
            params.put("sign", sign);
            String response = sendPostRequest(API_URL, params);
            result = response;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private String generateSign(Map<String, String> params) throws Exception {
        StringBuilder sb = new StringBuilder();
        if (plugin.getConfig().getInt("type") == 1){
            sb.append("money=").append(params.get("money")).append("&");
            sb.append("name=").append(params.get("name")).append("&");
            sb.append("notify_url=").append(params.get("notify_url")).append("&");
            sb.append("out_trade_no=").append(params.get("out_trade_no")).append("&");
            sb.append("pid=").append(params.get("pid")).append("&");
            sb.append("return_url=").append(params.get("return_url")).append("&");
            sb.append("type=").append(params.get("type"));
        }else{
            sb.append("clientip=").append(params.get("clientip")).append("&");
            sb.append("money=").append(params.get("money")).append("&");
            sb.append("name=").append(params.get("name")).append("&");
            sb.append("notify_url=").append(params.get("notify_url")).append("&");
            sb.append("out_trade_no=").append(params.get("out_trade_no")).append("&");
            sb.append("pid=").append(params.get("pid")).append("&");
            sb.append("return_url=").append(params.get("return_url")).append("&");
            sb.append("type=").append(params.get("type"));
        }
        sb.append(KEY);

        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] digest = md.digest(sb.toString().getBytes("UTF-8"));
        StringBuilder hexString = new StringBuilder();
        for (byte b : digest) {
            String hex = Integer.toHexString(0xff & b);
            if (hex.length() == 1) hexString.append('0');
            hexString.append(hex);
        }
        return hexString.toString();
    }

    private String sendPostRequest(String urlString, Map<String, String> params) throws Exception {
        URL url = new URL(urlString);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("POST");
        conn.setDoOutput(true);

        StringBuilder postData = new StringBuilder();
        for (Map.Entry<String, String> param : params.entrySet()) {
            if (postData.length() != 0) postData.append('&');
            postData.append(param.getKey()).append('=').append(param.getValue());
        }

        try (OutputStream os = conn.getOutputStream()) {
            byte[] input = postData.toString().getBytes("UTF-8");
            os.write(input, 0, input.length);
        }

        StringBuilder response = new StringBuilder();
        try (BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"))) {
            String responseLine;
            while ((responseLine = br.readLine()) != null) {
                response.append(responseLine.trim());
            }
        }

        return response.toString();
    }

}
